<?php


namespace App\Controller;

use Hyperf\Di\Annotation\Inject;
use Hyperf\Guzzle\ClientFactory;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\Utils\Codec\Json;
use Hyperf\Utils\Coroutine;
use Hyperf\Utils\Exception\ParallelExecutionException;
use Hyperf\Utils\Parallel;
use Hyperf\Utils\WaitGroup;
use Swoole\Coroutine\Channel;

/**
 * @Controller()
 */
class CoroutineController extends AbstractController
{
    /**
     * @Inject()
     * @var ClientFactory
     */
    private $clientFactory;

    private $cc;


    /**
     * @GetMapping(path="/coroutine")
     */
    public function co()
    {

//        Coroutine::create(function (){
//            sleep(3);
//            var_dump(time());
//        });
//
//        go(function () {
//            sleep(1);
//            var_dump(time());
//        });

//        // --------------------------------------------------
//        Coroutine::create(function () {
//            Context::set(self::getContextKey('cc'), 333);
//            var_dump(Context::get(self::getContextKey('cc')));
//            var_dump("------------------");
//        });
//
//        // Context在协程中与外部独立不共享
//        Context::set(self::getContextKey('cc'), 123);
//        go(function () {
//            var_dump(Context::get(self::getContextKey('cc')));
//            var_dump("------------------");
//        });

//        // ---------go协程一般用法--------------------------
//        go(function () {
//            $client = $this->clientFactory->create();
//            $res = $client->get('http://' . env('APP_HOST') . '/PrintInfo', [
//                'query' => [
//                    'key' => time()
//                ]
//            ]);
////            $code = $res->getStatusCode();
//            $info = $res->getBody()->getContents();
//
//            var_dump($info);
//        });
//        go(function () {
//            $client = $this->clientFactory->create();
//            $res = $client->get('http://' . env('APP_HOST') . '/PrintInfo', [
//                'query' => [
//                    'key' => time()
//                ]
//            ]);
////            $code = $res->getStatusCode();
//            $info = $res->getBody()->getContents();
//
//            var_dump($info);
//        });
//
//        // --------go协程+Channel队列---------------------------
//        $channel = new Channel();
//        go(function () use ($channel) {
//            $client = $this->clientFactory->create();
//            $res = $client->get('http://' . env('APP_HOST') . '/PrintInfo', [
//                'query' => [
//                    'key' => microtime()
//                ]
//            ]);
////            $code = $res->getStatusCode();
//            $info = $res->getBody()->getContents();
//            $info = Json::decode($info);
//            $info['index'] = 0;
//
//            $channel->push($info, 3);
//        });
//        go(function () use ($channel) {
//            $client = $this->clientFactory->create();
//            $res = $client->get('http://' . env('APP_HOST') . '/PrintInfo', [
//                'query' => [
//                    'key' => microtime()
//                ]
//            ]);
////            $code = $res->getStatusCode();
//            $info = $res->getBody()->getContents();
//            $info = Json::decode($info);
//            $info['index'] = 1;
//
//            $channel->push($info, 3);
//        });
//
//        $result[] = $channel->pop();
//        $result[] = $channel->pop();
//        var_dump($result);

//        // --------WaitGroup 为Channel的衍生版---------------------
//        $wg = new WaitGroup();
//        $result = [];
//        $wg->add(2);
//        co(function () use ($wg, &$result) {
//            $result[] = 123;
//            $wg->done();
//        });
//        co(function () use ($wg, &$result) {
//            $result[] = 234;
//            $wg->done();
//        });
//        $wg->wait();
//        var_dump($result);

        // ---------Parallel --------------------
        $parallel = new Parallel();
        $parallel->add(function () {
            $client = $this->clientFactory->create();
            $res = $client->get('http://' . env('APP_HOST') . '/PrintInfo', [
                'query' => [
                    'key' => time()
                ]
            ]);
            $info = $res->getBody()->getContents();
            $info = Json::decode($info);
            $info['index'] = 0;
            return $info;
        }, 'c');
        $parallel->add(function () {
            $client = $this->clientFactory->create();
            $res = $client->get('http://' . env('APP_HOST') . '/PrintInfo', [
                'query' => [
                    'key' => time()
                ]
            ]);
            $info = $res->getBody()->getContents();
            $info = Json::decode($info);
            $info['index'] = 1;
            return $info;
        }, 'b');

        try {
            $result = $parallel->wait();
            var_dump($result);
        } catch (ParallelExecutionException $e) {

        }
    }

    /**
     * @GetMapping("/PrintInfo")
     */
    public function printInfo()
    {
        $key = $this->request->input('key');
        return $this->response->json([
            'code' => 200,
            'key'  => $key,
            'time' => time(),
        ]);
    }
}